/* * Copyright 2016 Igor Maznitsa. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.igormaznitsa.sciareto.ui.tree; import java.awt.Point; import java.awt.datatransfer.DataFlavor; import java.awt.datatransfer.Transferable; import java.awt.dnd.DnDConstants; import java.awt.dnd.DragGestureEvent; import java.awt.dnd.DragGestureListener; import java.awt.dnd.DragSource; import java.awt.dnd.DragSourceDragEvent; import java.awt.dnd.DragSourceDropEvent; import java.awt.dnd.DragSourceEvent; import java.awt.dnd.DragSourceListener; import java.awt.dnd.DropTarget; import java.awt.dnd.DropTargetDragEvent; import java.awt.dnd.DropTargetDropEvent; import java.awt.dnd.DropTargetEvent; import java.awt.dnd.DropTargetListener; import java.awt.event.MouseEvent; import java.io.File; import java.util.Arrays; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.swing.DropMode; import javax.swing.JComponent; import javax.swing.JTree; import javax.swing.TransferHandler; import javax.swing.tree.TreeModel; import javax.swing.tree.TreePath; import javax.swing.tree.TreeSelectionModel; public final class DnDTree extends JTree implements DragSourceListener, DropTargetListener, DragGestureListener { private static final long serialVersionUID = -4915750239120689053L; private boolean dragAcceptableType = false; public DnDTree(){ super(); this.setDragEnabled(true); this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); this.setDropMode(DropMode.ON_OR_INSERT); final DragSource dragSource = DragSource.getDefaultDragSource(); dragSource.createDefaultDragGestureRecognizer(this,DnDConstants.ACTION_MOVE, this); final DropTarget dropTarget = new DropTarget(this, this); this.setTransferHandler(new TransferHandler() { private static final long serialVersionUID = 3109256773218160485L; @Override public boolean canImport(@Nonnull final TransferHandler.TransferSupport support) { return false; // return support.isDataFlavorSupported(DataFlavor.javaFileListFlavor); } @Override protected Transferable createTransferable(@Nonnull final JComponent c) { final JTree tree = (JTree) c; final TreePath selected = tree.getSelectionPath(); final NodeFileOrFolder item = (NodeFileOrFolder) selected.getLastPathComponent(); return new FileTransferable(Arrays.asList(item.makeFileForNode())); } @Override public boolean importData(@Nonnull final TransferHandler.TransferSupport support) { return canImport(support); } }); } @Override @Nullable public String getToolTipText(@Nonnull final MouseEvent evt) { if (getRowForLocation(evt.getX(), evt.getY()) == -1) { return null; } final TreePath curPath = getPathForLocation(evt.getX(), evt.getY()); final Object lastElement = curPath.getLastPathComponent(); if (lastElement instanceof NodeFileOrFolder) { final File file = ((NodeFileOrFolder) lastElement).makeFileForNode(); return file == null ? null : file.getAbsolutePath(); } else { return null; } } public void focusToFirstElement(){ final TreeModel model = this.getModel(); final Object root = model.getRoot(); if (root != null){ final Object firstChild = model.getChildCount(root)>0 ? model.getChild(root, 0) : null; if (firstChild!=null){ this.setSelectionPath(new TreePath(new Object[]{root,firstChild})); } } } @Override public void dragEnter(@Nonnull final DragSourceDragEvent dsde) { } @Override public void dragOver(@Nonnull final DragSourceDragEvent dsde) { } @Override public void dropActionChanged(@Nonnull final DragSourceDragEvent dsde) { } @Override public void dragExit(@Nonnull final DragSourceEvent dse) { } @Override public void dragDropEnd(@Nonnull final DragSourceDropEvent dtde) { } @Override public void dragEnter(@Nonnull final DropTargetDragEvent dtde) { dtde.rejectDrag(); // // this.dragAcceptableType = checkDragType(dtde); // if (!this.dragAcceptableType) { // dtde.rejectDrag(); // } } @Override public void dragOver(@Nonnull final DropTargetDragEvent dtde) { if (!this.dragAcceptableType){ dtde.rejectDrag(); } } @Override public void dropActionChanged(@Nonnull DropTargetDragEvent dtde) { } @Override public void dragExit(@Nonnull final DropTargetEvent dte) { } @Override public void drop(@Nonnull final DropTargetDropEvent dtde) { if (this.dragAcceptableType) { final Point dragPoint = dtde.getLocation(); final TreePath path = getPathForLocation(dragPoint.x, dragPoint.y); if (path != null) { final Object dropTargetNode = path.getLastPathComponent(); if (dropTargetNode instanceof NodeFileOrFolder) { final NodeFileOrFolder node = (NodeFileOrFolder) dropTargetNode; if (!node.isLeaf()) { //TODO processing of file drag in tree System.out.println("Not implemented yet!"); //NOI18N } else { dtde.rejectDrop(); } } } repaint(); } } protected static boolean checkDragType(@Nonnull final DropTargetDragEvent dtde) { boolean result = false; for (final DataFlavor flavor : dtde.getCurrentDataFlavors()) { final Class dataClass = flavor.getRepresentationClass(); if (FileTransferable.class.isAssignableFrom(dataClass) || flavor.isFlavorJavaFileListType()) { result = true; break; } } return result; } @Override public void dragGestureRecognized(@Nonnull final DragGestureEvent dragGestureEvent) { final JTree tree = (JTree) dragGestureEvent.getComponent(); final TreePath path = tree.getSelectionPath(); if (path != null) { final Object selection = path.getLastPathComponent(); if (selection instanceof NodeFileOrFolder){ FileTransferable node = new FileTransferable(Arrays.asList(((NodeFileOrFolder)selection).makeFileForNode())); dragGestureEvent.startDrag(DragSource.DefaultCopyDrop, node, this); } } } }